package com.liang.gulimall.search.thread;

import java.util.concurrent.*;

public class ThreadTest {
    public static ExecutorService executorService= Executors.newFixedThreadPool(10);
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main start。。");
        /**
         * 创建线程池的四种方式
         */
//        new Thread01().start();//方式一
//        new Thread(new Runnable01()).start();//方式二

//        FutureTask<Integer> futureTask = new FutureTask<>(new Callable01());
//        new Thread(futureTask).start();
//
//        Integer integer = futureTask.get();//等待线程结束拿到结果，此时main线程等待
//        System.out.println(integer);

//        executorService.submit(new Runnable01()); //方式4,使用线程池
        /**
         * 异步编排测试============================================================================>
         */
        /**
         * 开启一个异步任务无返回值
         */
        /*CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
            System.out.println("-------开启一个异步任务无返回值--------");
            try {
                Thread.sleep(1000);
                System.out.println(10 / 5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, executorService);*/
        /**
         * 开启一个异步任务有返回值,感知异常
         */
/*        CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("-------开启一个异步任务有返回值,感知异常--------");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 100/0;
        }, executorService).whenComplete((res,e)->{
            //可以感知异常，不能处理
            System.out.println("异步任务完成后，的操作。。");
            System.out.println("结果："+res+",异常："+e);
        }).exceptionally(throwable -> {
            //有异常返回默认值
            return 999;
        });
        Integer integer = future.get();
        System.out.println("返回结果："+integer);*/

        /**
         * 开启一个异步任务有返回值,handle处理
         */
        /*CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("-------开启一个异步任务有返回值,handle处理--------");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 100;
        }, executorService).handle((res,e)->{
            if (res!=null){
                return res*888;
            }
            if (e!=null){
                //有异常
                return 0;
            }
            return 888;
        });
        Integer integer = future.get();
        System.out.println("返回结果："+integer);*/
        /**
         * //thenRun不能得到上个线程的执行结果
         */
        /*CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("-------开启一个异步任务,串行化--------");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 100;
        }, executorService).thenRunAsync(()->{//thenRun不能得到上个线程的执行结果
            System.out.println("第二个任务启动");
        },executorService);*/
        /**
         * thenAccept能得到上个线程的执行结果,但是没有返回值
         */
        /*CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("-------开启一个异步任务,串行化--------");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 100;
        }, executorService).thenAcceptAsync((res)->{//thenAccept能得到上个线程的执行结果,但是没有返回值
            System.out.println("第二个任务,上个线程结果："+res);
        },executorService);*/

        /**
         * thenApply能得到上个线程的执行结果,还有返回值
         */
        /*CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("-------开启一个异步任务,串行化--------");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 100;
        }, executorService).thenApplyAsync(res -> {//thenApply能得到上个线程的执行结果,还有返回值
            return res * 2;
        }, executorService);
        System.out.println("2结束："+future.get());*/
        /**
         * 两任务组合都要完成
         *
         */
        //两任务都要完成
        CompletableFuture<Integer> future01 = CompletableFuture.supplyAsync(() -> {
            System.out.println("-------开启一个异步任务1--------");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("-------结束1--------");
            return 100;
        }, executorService);
        CompletableFuture<String> future02 = CompletableFuture.supplyAsync(() -> {
            System.out.println("-------开启一个异步任务2--------");
            System.out.println("-------结束2--------");
            return "hello";
        }, executorService);
        /**
         * //1,2都完成后运行任务3,不能拿到1和2的结果
         */
//        future01.runAfterBothAsync(future02,()->{//1,2都完成后运行任务3,不能拿到1和2的结果
//            System.out.println("异步任务3");
//        },executorService);
        /**
         * //1,2都完成后运行任务3,能拿到1和2的结果
         */
//        future01.thenAcceptBothAsync(future02,(res1,res2)->{//1,2都完成后运行任务3,能拿到1和2的结果
//            System.out.println("异步任务3");
//            System.out.println("任务1结果："+res1+",任务二结果;"+res2);
//        },executorService);
        /**
         * //1,2都完成后运行任务3,能拿到1和2的结果,而且有返回值
         */
//        CompletableFuture<String> future03 = future01.thenCombineAsync(future02, (res1, res2) -> {//1,2都完成后运行任务3,能拿到1和2的结果,而且有返回值
//            return res1 + res2;
//        }, executorService);
//        String s = future03.get();
//        System.out.println(s);

        //两任务有一个完成，就执行任务三
        /**
         * 两任务有一个完成，就执行任务三
         * runAfterEitherAsync:_不感知结果,自己没有诉回值
         * acceptEitherAsync:感知结果,自己没有返回值
         * applyToEitherAsync:感知结果,自己有返回值
         */

        //多任务
        /**
         * //等待所有任务完成
         */
//        CompletableFuture<Void> future = CompletableFuture.allOf(future01, future02, future03, future04);
//        future.get();//等待所有任务完成
        /**
         * //有一个完成就可以
         */
//        CompletableFuture<Object> future = CompletableFuture.anyOf(future01, future02, future03, future04);
//        future.get();//有一个完成就可以
        System.out.println("main end。。");
    }

    /**
     * 开启一个线程方式一、继承Thread
     */
    public static class Thread01 extends Thread {
        public void run(){
            System.out.println("-------开启一个线程方式一、继承Thread");
            try {
                Thread.sleep(1000);
                System.out.println(10/5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 开启一个线程方式二、实现Runnable
     */
    public static class Runnable01 implements Runnable{

        @Override
        public void run() {
            System.out.println("-------开启一个线程方式二、实现Runnable");
            try {
                Thread.sleep(1000);
                System.out.println(10/5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * 开启一个线程方式三、实现Callable<V> 配合FutureTask得到线程返回结果
     */
    public static class Callable01 implements Callable<Integer> {

        @Override
        public Integer call() throws Exception {
            try {
                //处理业务
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 111;
        }
    }

    /**
     * 开启一个线程方式四、创建线程池
     *  1、使用提供的 public static ExecutorService service= Executors.newFixedThreadPool(10);
     *  2、new ThreadPoolExecutor(int corePoolSize,
     *                               int maximumPoolSize,
     *                               long keepAliveTime,
     *                               TimeUnit unit,
     *                               BlockingQueue<Runnable> workQueue,
     *                               ThreadFactory threadFactory,
     *                               RejectedExecutionHandler handler)
     *      工作顺序:
     *      1)、线程池创建,准备好core数量的核心线程,准备接受任务
     *       1.1、core满了，就将再进来的任务放入阻塞队列中。空闲的core就会自己去阻塞队列获取任务执行
     *       1.2、阻塞队列满了，就直接开新线程执行，最大只能开到max指定的数量
     *       1.3、max满了就用RejectedExecutionHandLer拒绝任务
     *       1.4、max都执行完成，有很多空闲.在指定的时间keepAliveTime以后，释放max-core这些线程
     *
     */

    /**
     * 方式1和方式2:主进程无法获取线程的运算结果。不适合当前场景
     * 方式3:主进程可以获取线程的运算结果，但是不利于控制服务器中的线程资源。可以导致服务器资源耗尽。
     * 方式4通过如上两种方式初始化线程池 通过线程池性能稳定，也可以获取执行结果，并捕获异常。
     *     但是，在业务复杂情况下，一个异步调用可能会依赖于另一个异步调用的执行结果。
     */
    /**
     * 为什么使用线程池：
     * 1、使用已经创建好的线程降低资源消耗，避免反复创建和销毁线程带来的损耗
     * 2、提高响应速度，创建和销毁浪费时间
     * 3、可管理性，避免系统资源耗尽
     */

    /*
    * 异步编排
    *
    *
    * */


}
